package com.bidepan.spring6.aop.example;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

//动态代理类制造工厂
public class ProxyFactory {
    //目标对象
    private Object target;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //返回代理对象
    public Object getProxy(){
        /**
         * Proxy.newInstance()方法来返回一个代理类
         * 有三个参数
         * 第一个参数：ClassLoader：加载动态生成代理类的类加载器
         * 第二个参数：Class<?>[] interfaces：目标对象实现的所有接口的class类型数组
         * 第三个参数：InvocationHandler：设置代理对象实现目标方法的过程
         **/
        //得到第一个参数ClassLoader
        ClassLoader classLoader = target.getClass().getClassLoader();
        //得到第二个参数Class<?>[] interfaces：目标对象的所有接口的Class
        Class<?>[] interfaces = target.getClass().getInterfaces();

        //得到第三个参数InvocationHandler：设置代理对象的实现目标方法的过程
        InvocationHandler invocationHandler = new InvocationHandler(){
            /**
             * invoke()：实现目标方法的过程
             * 第一个参数：proxy：代理对象
             * 第二个参数：method：需要重写目标对象的方法
             * 第三个参数：args：method方法所需参数
             **/
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //额外过程1：目标方法调用前输出日志
                System.out.println("[动态代理][日志] "+method.getName()+"，参数："+ Arrays.toString(args));
                //调用目标的方法
                Object result = method.invoke(target,args);
                //额外过程2：目标方法调用后输出日志
                System.out.println("[动态代理][日志] "+method.getName()+"，执行完毕");
                return result;
            }
        };

        //返回动态代理类
        return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    }
}
